function pinlvyusudu
    % 多普勒效应演示程序

    % 清除工作区和关闭所有图形窗口
    clearvars; close all; clc;

    % 创建图形用户界面（GUI）
    fig = figure('Name', '多普勒效应演示', 'NumberTitle', 'off', ...
        'Position', [100, 100, 800, 700], 'Resize', 'off');

    % 默认发射频率（Hz）
    defaultFreq = 5000; % 增加默认频率至5000Hz

    % 创建频率输入框和标签
    uicontrol('Style', 'text', 'Position', [50, 650, 120, 25], 'String', '频率 (Hz):', ...
        'HorizontalAlignment', 'left', 'FontSize', 12);
    freqEdit = uicontrol('Style', 'edit', 'Position', [180, 650, 120, 30], ...
        'String', num2str(defaultFreq), 'FontSize', 12);

    % 创建“开始”和“停止”按钮
    startButton = uicontrol('Style', 'pushbutton', 'Position', [50, 570, 150, 50], ...
        'String', '开始', 'FontSize', 14, 'Callback', @startCallback);
    stopButton = uicontrol('Style', 'pushbutton', 'Position', [220, 570, 150, 50], ...
        'String', '停止', 'FontSize', 14, 'Callback', @stopCallback, 'Enable', 'off');

    % 创建用于绘图的坐标轴
    axesHandle = axes('Units', 'pixels', 'Position', [50, 250, 700, 300]);
    xlabel('时间 (s)', 'FontSize', 12);
    ylabel('频率 (Hz)', 'FontSize', 12);
    title('检测到的频率', 'FontSize', 14);
    grid on;

    % 创建文本框显示当前检测频率
    currentFreqText = uicontrol('Style', 'text', 'Position', [500, 650, 250, 30], ...
        'String', '当前频率: -- Hz', 'FontSize', 12, 'HorizontalAlignment', 'left');
    % 创建文本框显示当前速度
    currentSpeedText = uicontrol('Style', 'text', 'Position', [500, 620, 250, 30], ...
        'String', '当前速度: -- m/s', 'FontSize', 12, 'HorizontalAlignment', 'left');

    % 初始化全局变量
    isRecording = false; % 控制录音循环的标志
    player = []; % 音频播放对象
    recorder = []; % 音频录制对象
    detectedFrequencies = []; % 存储检测到的频率
    detectedSpeeds = []; % 存储检测到的速度
    timeStamps = []; % 存储时间戳
    Fs = 44100; % 采样率（Hz）
    v_sound = 343; % 声音速度（m/s）
    minValidDetections = 5; % 开始绘图前需要的最小有效检测次数

    emittedFreq = []; % 在主函数中声明 emittedFreq 变量

    % 开始按钮的回调函数
    function startCallback(~, ~)
        % 获取用户输入的发射频率
        emittedFreqStr = get(freqEdit, 'String');
        emittedFreq = str2double(emittedFreqStr);
        if isnan(emittedFreq) || emittedFreq <= 0
            errordlg('请输入有效的频率。', '输入错误');
            return;
        end

        % 根据发射频率动态调整频率变化阈值
        validFreqThreshold = 0.3 * emittedFreq; % 设置为发射频率的30%

        % 禁用频率输入框和开始按钮，启用停止按钮
        set(freqEdit, 'Enable', 'off');
        set(startButton, 'Enable', 'off');
        set(stopButton, 'Enable', 'on');

        % 生成持续60秒的声音信号
        duration = 60; % 持续时间（秒）
        t = 0:1/Fs:duration;
        y = sin(2*pi*emittedFreq*t)';

        % 创建音频播放对象并开始播放
        player = audioplayer(y, Fs);
        play(player);

        % 创建音频录制对象并开始录制
        recorder = audiorecorder(Fs, 16, 1);
        record(recorder);

        % 初始化变量
        isRecording = true;
        detectedFrequencies = [];
        detectedSpeeds = [];
        timeStamps = [];
        tic; % 开始计时

        % 绘制参考线
        hold(axesHandle, 'on');
        refLine = plot(axesHandle, [0, duration], [emittedFreq, emittedFreq], 'r--', 'LineWidth', 1.5);
        hold(axesHandle, 'off');

        % 初始化有效检测计数
        validDetections = 0;

        % 开始实时分析循环
        while isRecording
            pause(0.1); % 调整暂停时间以控制更新频率（增加检测频率点）
            % 获取录制的音频数据
            audioData = getaudiodata(recorder);
            % 只处理最新的0.2秒数据以提高频率分辨率
            analysisWindow = 0.2; % 秒
            if length(audioData) > Fs * analysisWindow
                audioChunk = audioData(end - floor(Fs * analysisWindow) + 1:end);
            else
                audioChunk = audioData;
            end

            % 进行快速傅里叶变换（FFT）以检测频率
            N = length(audioChunk);
            % 零填充到16384点以提高频率分辨率
            N_fft = 16384;
            fftData = abs(fft(audioChunk .* hamming(N), N_fft));
            fftData = fftData(1:floor(N_fft/2)+1);
            f = (0:floor(N_fft/2)) * Fs / N_fft;

            % 找到峰值频率
            [~, idx] = max(fftData);

            % 使用二次插值提高频率估计精度
            if idx > 1 && idx < length(fftData)
                alpha = fftData(idx-1);
                beta = fftData(idx);
                gamma = fftData(idx+1);
                p = 0.5 * (alpha - gamma) / (alpha - 2*beta + gamma);
                detectedFreq = f(idx) + p * (Fs / N_fft);
            else
                detectedFreq = f(idx);
            end

            % 检查检测到的频率是否在有效范围内
            if detectedFreq >= (emittedFreq - validFreqThreshold) && detectedFreq <= (emittedFreq + validFreqThreshold)
                % 存储检测到的频率和时间戳
                detectedFrequencies(end+1) = detectedFreq;
                timeStamps(end+1) = toc;

                % 计算速度
                v_observer = v_sound * (detectedFreq / emittedFreq - 1);

                % 存储检测到的速度
                detectedSpeeds(end+1) = v_observer;

                % 更新当前频率和速度显示
                set(currentFreqText, 'String', sprintf('当前频率: %.2f Hz', detectedFreq));
                set(currentSpeedText, 'String', sprintf('当前速度: %.2f m/s', v_observer));

                % 更新有效检测计数
                validDetections = validDetections + 1;
            else
                % 忽略无效的频率检测
                continue;
            end

            % 仅在达到最小有效检测次数后开始绘图
            if validDetections >= minValidDetections
                % 实时更新绘图
                cla(axesHandle);
                hold(axesHandle, 'on');
                % 使用样条插值（spline）进行插值以生成更平滑的曲线
                if length(timeStamps) >= 2
                    interpTime = linspace(min(timeStamps), max(timeStamps), 10 * length(timeStamps));
                    interpFreq = spline(timeStamps, detectedFrequencies, interpTime);
                    plot(axesHandle, interpTime, interpFreq, 'b-', 'LineWidth', 1.5);
                else
                    plot(axesHandle, timeStamps, detectedFrequencies, 'b-', 'LineWidth', 1.5);
                end
                plot(axesHandle, [0, max(timeStamps)+1], [emittedFreq, emittedFreq], 'r--', 'LineWidth', 1.5); % 参考线
                hold(axesHandle, 'off');
                xlabel('时间 (s)', 'FontSize', 12);
                ylabel('频率 (Hz)', 'FontSize', 12);
                title('检测到的频率', 'FontSize', 14);
                grid on;

                % 固定Y轴范围为发射频率上下15 Hz
                ylim([emittedFreq - 15, emittedFreq + 15]);

                drawnow;
            end
        end
    end

    % 停止按钮的回调函数
    function stopCallback(~, ~)
        % 停止录音和播放
        isRecording = false;
        if ~isempty(player)
            stop(player);
        end
        if ~isempty(recorder)
            stop(recorder);
        end

        % 启用频率输入框和开始按钮，禁用停止按钮
        set(freqEdit, 'Enable', 'on');
        set(startButton, 'Enable', 'on');
        set(stopButton, 'Enable', 'off');

        % 检查是否有检测到的数据
        if isempty(detectedFrequencies) || isempty(detectedSpeeds) || isempty(timeStamps)
            errordlg('未检测到有效的频率或速度数据。', '数据错误');
            return;
        end

        % 获取屏幕大小
        screenSize = get(0, 'ScreenSize');
        screenWidth = screenSize(3);
        screenHeight = screenSize(4);

        % 定义图形窗口的大小
        figWidth = 1000;
        figHeight = 600;

        % 计算图形窗口的位置，确保窗口不会超出屏幕范围
        posX = min(100, screenWidth - figWidth - 100); % 保持在屏幕左侧
        posY = min(100, screenHeight - figHeight - 100); % 保持在屏幕底部

        % 创建一个新的图形窗口，用于显示两个子图
        finalFig = figure('Name', '分析结果', 'NumberTitle', 'off', ...
            'Position', [posX, posY, figWidth, figHeight]);

        % 确保 finalFig 是当前图形窗口
        figure(finalFig);

        % 创建两个子图：一个用于频率变化，另一个用于速度变化

        % 频率变化子图
        subplot(2, 1, 1);
        hold on;
        % 使用样条插值生成更平滑的频率曲线
        if length(timeStamps) >= 2
            interpTimeFreq = linspace(min(timeStamps), max(timeStamps), 10 * length(timeStamps));
            interpFreq = spline(timeStamps, detectedFrequencies, interpTimeFreq);
            plot(interpTimeFreq, interpFreq, 'b-', 'LineWidth', 1.5);
        else
            plot(timeStamps, detectedFrequencies, 'b-', 'LineWidth', 1.5);
        end
        % 绘制发射频率参考线
        plot([0, max(timeStamps)+1], [emittedFreq, emittedFreq], 'r--', 'LineWidth', 1.5);
        hold off;
        xlabel('时间 (s)', 'FontSize', 12);
        ylabel('频率 (Hz)', 'FontSize', 12);
        title('频率随时间的变化', 'FontSize', 14);
        grid on;
        ylim([emittedFreq - 15, emittedFreq + 15]);
        xlim([0, max(timeStamps)+1]);
        legend('检测频率', '发射频率', 'Location', 'best');

        % 速度变化子图
        subplot(2, 1, 2);
        hold on;
        % 使用样条插值生成更平滑的速度曲线
        if length(timeStamps) >= 2
            interpTimeSpeed = linspace(min(timeStamps), max(timeStamps), 10 * length(timeStamps));
            interpSpeed = spline(timeStamps, detectedSpeeds, interpTimeSpeed);
            plot(interpTimeSpeed, interpSpeed, 'g-', 'LineWidth', 1.5);
        else
            plot(timeStamps, detectedSpeeds, 'g-', 'LineWidth', 1.5);
        end
        hold off;
        xlabel('时间 (s)', 'FontSize', 12);
        ylabel('速度 (m/s)', 'FontSize', 12);
        title('速度随时间的变化', 'FontSize', 14);
        grid on;
        xlim([0, max(timeStamps)+1]);
        ylim auto; % 让Y轴根据数据自动调整
        legend('检测速度', 'Location', 'best');

        % 设置图形背景颜色为白色
        set(finalFig, 'Color', 'w'); 

        % 确保图形窗口保持打开状态
        set(finalFig, 'HandleVisibility', 'on');
    end
end
